package com.lvcoding.auth2.auth.shizhan.verifycode.parent;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.context.request.ServletWebRequest;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 验证码抽象类
 *
 * @author wuyanshen
 */
public abstract class AbstractVerifyCodeHandler<C> implements VerifyCodeHandler<C> {

    @Override
    public C handle(ServletWebRequest servletWebRequest) throws Exception {
        C verifyCode = this.generateCode(servletWebRequest);
        this.saveCode(servletWebRequest, verifyCode);
        this.sendCode(servletWebRequest, verifyCode);
        return verifyCode;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void saveCode(ServletWebRequest servletWebRequest, C verifyCode) throws Exception {
//        String phone = ServletRequestUtils.getStringParameter(servletWebRequest.getRequest(), "mobile");
        RedisTemplate redisTemplate = SpringUtil.getBean("redisTemplate");
        String type = getProcessorType(servletWebRequest);
        redisTemplate.opsForValue().set(VerifyCodeHandler.VERIFY_CODE_KEY + type, verifyCode, 5, TimeUnit.MINUTES);
    }

    @Override
    @SuppressWarnings("unchecked")
    public C generateCode(ServletWebRequest servletWebRequest) throws Exception {
        String type = getProcessorType(servletWebRequest);
        Map<String, VerifyCodeGenerator> verifyCodeGeneratorMap = SpringUtil.getBeansOfType(VerifyCodeGenerator.class);
        VerifyCode verifyCode = verifyCodeGeneratorMap.get(type + "VerifyCodeGenerator").generate(servletWebRequest);
        return (C)verifyCode;
    }

    private String getProcessorType(ServletWebRequest request) {
        return StrUtil.subAfter(request.getRequest().getRequestURI(), "/code/", false);
    }

    /**
     * 发送验证码，留给子类实现
     */
    protected abstract void sendCode(ServletWebRequest servletWebRequest, C verifyCode) throws Exception;
}
